El análisis de los datos se realizó utilizando R (ver tarea3_parte2.Rmd).
Primero realizamos una visualización exploratoria de las 85 características de los animales
boxplot(datos, col = "deepskyblue", main = "Datos",
xlab = "Variable", ylab = "Valor")
summary(datos[,c(1,5,20,60)])
## V1 V5 V20 V60
## Min. :-1.00 Min. : 0.000 Min. : 0.000 Min. : 0.0000
## 1st Qu.:11.15 1st Qu.: 6.315 1st Qu.: 0.000 1st Qu.: 0.8525
## Median :34.34 Median :24.115 Median : 0.000 Median : 5.1700
## Mean :35.35 Mean :26.747 Mean : 6.693 Mean : 9.1574
## 3rd Qu.:47.34 3rd Qu.:39.330 3rd Qu.: 6.008 3rd Qu.:12.4425
## Max. :91.55 Max. :83.970 Max. :77.770 Max. :60.8500
Con la información anterior podemos observar que las variables se encuentran en un rango de -1 a 100, sin embargo, es difícil hacer un análisis más preciso debido a que se tiene un gran número de categorías y además no se sabe la característica que representan.
Ahora realizaremos las visualizaciones ISOMAP, LLE, T-SNE y SOM sobre el conjunto de datos.
Realizamos ISOMAP para proyectar en 3 dimensiones utilizando 5 vecinos más cercanos y mostramos la gráfica a pares de los resultados:
library(dimRed)
emb <- embed(datos, "Isomap", .mute = NULL, knn = 5, ndim = 3)
plot(as.data.frame(emb@data),col="blue")
Gráficamos los puntos proyectados para las dimensiones 1 y 2 y también realizamos una gráfica en formato html para facilitar la visualización
library(viridis)
N <- nrow(datos_clases)
pal_col <- viridis(N)
plot(Proy[,1], Proy[,2], col = "white")
text(Proy[,1], Proy[,2], datos_clases$clases, col = pal_col, cex = .8)
library(plotly)
plot_ly(data = datos_clases, x = ~iso.1, y = ~iso.2, color = ~clases)
Gráficamos los puntos proyectados para las dimensiones 1 y 3 y también realizamos la gráfica en formato html
N <- nrow(datos_clases)
pal_col <- rainbow(N)
plot(Proy[,1], Proy[,3], col = "white")
text(Proy[,1], Proy[,3], datos_clases$clases, col = pal_col, cex = .8)
plot_ly(data = datos_clases, x = ~iso.1, y = ~iso.3, color = ~clases)
Ahora para las dimensiones 2 y 3
N <- nrow(datos_clases)
pal_col <- viridis(N)
plot(Proy[,2], Proy[,3], col = "white")
text(Proy[,2], Proy[,3], datos_clases$clases, col = pal_col, cex = .8)
plot_ly(data = datos_clases, x = ~iso.2, y = ~iso.3, color = ~clases)
Por último para tener una visualización más general, realizamos una gráfica interactiva con las 3 dimensiones
fig3D <- plot_ly(data = datos_clases, x = ~iso.1, y = ~iso.2, z = ~iso.3, color = ~clases)
fig3D
Podemos observar que tanto la dimensión 1 como la dimensión 2 son capaces de distinguir a las ballenas, la dimensión 1 también distigue a los animales marinos en general como (morsa, delfin y foca además de la ballenas), utilizando ambas dimensiones podemos distiguir entre 2 tipos de animales marinos (los que son ballenas y los que no). También podemos notar que ambas dimensiones combinadas distinguen facilmente a roedores medianos como ardilla, castor y nutria.
La dimensión 1 también permite distiguir entre animales hervívoros, omnívoros, carnívoros y piscívoros. Los valores negativos de la dimensión 3 parecen hacer referencia a animales que son inofensivos como animales domésticos o muy pequeños, mientras mayor es el valor de esta dimensión podríamos pensar que los animales son más grandes y agresivos.
Al observar el resultado con las 3 dimensiones combinadas, es clara la separación de los animales marinos, animales grandes y carnívoros como el león el tigre y el leopardo, también podemos ver separaciones de los primates como el chimpancé y el gorila. Animales medianos y con forma similar como el lince, el lobo y el pastor alemán se observan también cercanos.
Realizamos LLE para proyectar en 3 dimensiones utilizando 5 vecinos más cercanos y un umbral de 0.9.
library(lle)
lle_k5 <- lle(datos, m=3, k=5, id=TRUE, v=0.9)
## finding neighbours
## calculating weights
## intrinsic dim: mean=3.6, mode=4
## computing coordinates
Gráficamos los puntos proyectados dim 1 vs dim 2
N <- nrow(datos_clases)
pal_col <- viridis(N)
plot(Proy[,1], Proy[,2], col = "white")
text(Proy[,1], Proy[,2], datos_clases$clases, col = pal_col, cex = .8)
plot_ly(data = datos_clases, x = ~lle.1, y = ~lle.2, color = ~clases)
Gráficamos los puntos proyectados dim 1 vs dim 3
N <- nrow(datos_clases)
pal_col <- rainbow(N)
plot(Proy[,1], Proy[,3], col = "white")
text(Proy[,1], Proy[,3], datos_clases$clases, col = pal_col, cex = .8)
plot_ly(data = datos_clases, x = ~lle.1, y = ~lle.3, color = ~clases)
Gráficamos los puntos proyectados dim 2 vs dim 3
N <- nrow(datos_clases)
pal_col <- viridis(N)
plot(Proy[,2], Proy[,3], col = "white")
text(Proy[,2], Proy[,3], datos_clases$clases, col = pal_col, cex = .8)
plot_ly(data = datos_clases, x = ~lle.2, y = ~lle.3, color = ~clases)
Gráfica en 3D
fig3D <- plot_ly(data = datos_clases, x = ~lle.1, y = ~lle.2, z = ~lle.3, color = ~clases)
fig3D
Podemos notar que la dimensión 1 permite distiguir animales como felinos, caninos, bóvidos como el búfalo, antílope y venado y roedores. La dimensión 2 distingue animales cuadrúpedos como lobos y perros de animales bípedos como osos y primates además distigue también animales con cuernos o colmillos grandes como el rinoceronte, antílope e hipopótamo de los animales marinos. La dimensión 3 distingue animales domésticos, tamaños y formas.
Al observar las 3 dimensiones se puede realizar una mejor interpretación de la reducción de dimensionalidad ya que se distinguen por lo menos 7 grupos:
Realizamos T-SNE para proyectar en 3 dimensiones utilizando el parámetro perplexity \(\sigma = 10\) fijamos también el parámetro \(\theta = 0\) para ejecutar el método de forma exacta.
library(Rtsne)
set.seed(123)
tsne_out <- Rtsne(datos,dims = 3,pca=FALSE,perplexity=10,theta=0.0)
Proy <- as.data.frame(tsne_out$Y)
Gráficamos los puntos proyectados dim 1 vs dim 2
N <- nrow(datos_clases)
pal_col <- viridis(N)
plot(Proy[,1], Proy[,2], col = "white")
text(Proy[,1], Proy[,2], datos_clases$clases, col = pal_col, cex = .8)
plot_ly(data = datos_clases, x = ~tsne.1, y = ~tsne.2, color = ~clases)
Gráficamos los puntos proyectados dim 1 vs dim 3
N <- nrow(datos_clases)
pal_col <- rainbow(N)
plot(Proy[,1], Proy[,3], col = "white")
text(Proy[,1], Proy[,3], datos_clases$clases, col = pal_col, cex = .8)
plot_ly(data = datos_clases, x = ~tsne.1, y = ~tsne.3, color = ~clases)
Gráficamos los puntos proyectados dim 2 vs dim 3
N <- nrow(datos_clases)
pal_col <- viridis(N)
plot(Proy[,2], Proy[,3], col = "white")
text(Proy[,2], Proy[,3], datos_clases$clases, col = pal_col, cex = .8)
plot_ly(data = datos_clases, x = ~tsne.2, y = ~tsne.3, color = ~clases)
Gráfica en 3D
fig3D <- plot_ly(data = datos_clases, x = ~tsne.1, y = ~tsne.2, z = ~tsne.3, color = ~clases)
fig3D
La dimensión 1 de la proyección distingue entre tipos de animales como felinos, osos, animales domésticos, roedores, también se observa que los primates están cerca, los animales de granja como la vaca, el cerdo y el caballo se encuentran con proyecciones similares, los bóvidos, los animales grandes no marinos y animales grandes marinos como el hipopótamo. La dimensión 2 permite distiguir entre la alimentación de los animlaes, como hervíboros, los que se alimentan de semillas como roedores, los carnívoros y los piscívoro. La dimensión 3 distingue un poco entre animales con cuernos y formas.
Las gráfica de las 3 dimensiones combinadas permite hacer observar grupos muy definidos como:
Realizamos el algoritmo SOM para proyectar en 12 canastas definidas mediante una rejilla de forma rectangular.
require(kohonen)
require(RColorBrewer)
library(RCurl)
set.seed(123)
datos_som <- as.data.frame(datos)
som <- som(scale(datos_som), grid = somgrid(4, 3, "rectangular"))
La siguiente gráfica muestra el peso que representa cada uno de los 85 atributos para la elección de los puntos en cada una de las canastas.
plot(som)
Ahora mostramos el mapa de calor el cual nos indica la concentración de animales en cada una de las canastas.
colors <- function(n, alpha = 1) rev(heat.colors(n, alpha))
plot(som, type = "counts", palette.name = colors, heatkey = TRUE)
Detalle de animales en cada canasta
datos_clases <- cbind(clases=clases[,2], som$unit.classif)
split(datos_clases,datos_clases$V2)
## $`1`
## clases.V2 V2
## 1: antelope 1
## 2: horse 1
## 3: moose 1
## 4: giraffe 1
## 5: zebra 1
## 6: deer 1
##
## $`2`
## clases.V2 V2
## 1: hippopotamus 2
## 2: elephant 2
## 3: ox 2
## 4: sheep 2
## 5: rhinoceros 2
## 6: buffalo 2
## 7: pig 2
## 8: cow 2
##
## $`3`
## clases.V2 V2
## 1: beaver 3
## 2: otter 3
##
## $`4`
## clases.V2 V2
## 1: killer+whale 4
## 2: blue+whale 4
## 3: humpback+whale 4
## 4: seal 4
## 5: walrus 4
## 6: dolphin 4
##
## $`5`
## clases.V2 V2
## 1: hamster 5
## 2: squirrel 5
## 3: rabbit 5
## 4: mouse 5
##
## $`6`
## clases.V2 V2
## 1: giant+panda 6
##
## $`7`
## clases.V2 V2
## 1: dalmatian 7
## 2: persian+cat 7
## 3: chihuahua 7
## 4: collie 7
##
## $`8`
## clases.V2 V2
## 1: grizzly+bear 8
## 2: polar+bear 8
##
## $`9`
## clases.V2 V2
## 1: skunk 9
## 2: mole 9
## 3: bat 9
## 4: rat 9
## 5: raccoon 9
##
## $`10`
## clases.V2 V2
## 1: spider+monkey 10
## 2: gorilla 10
## 3: chimpanzee 10
##
## $`11`
## clases.V2 V2
## 1: german+shepherd 11
## 2: siamese+cat 11
## 3: weasel 11
##
## $`12`
## clases.V2 V2
## 1: tiger 12
## 2: leopard 12
## 3: fox 12
## 4: wolf 12
## 5: bobcat 12
## 6: lion 12
Podemos notar los siguiente respecto a cada canasta:
Canasta 1: se encuentran animales cuadrúpedos grandes y hervíboros.
Canasta 2: se encuentran animales también hervívoros y cuadrúpedos pero más anchos o más densos que los de la canasta 1.
Canasta 3: aquí están los 2 animales semiacuáticos parecidos que son la nutria y el castor.
Canasta 4: están los animlaes acuáticos incluyendo a las ballenas.
Canasta 5: se encuentran los roedores pequeños.
Canasta 6: solamente está el panda.
Canasta 7: animales domésticos pequeños o medianos.
Canasta 8: están los osos.
Canasta 9: mamíferos pequeños (murciélago, la rata, el mapache, etc.)
Canasta 10: están los primates.
Canasta 11: se encuentran más animales domésticos.
Canasta 12: aquí están todos los felinos y caninos salvajes.
Realizamos el agrupamiento utilizando Single linkage
clusters <- hclust(dist(scale(datos)), method = "single")
plot(clusters, col = "blue")
Cortamos para formar 12 clústers
clusterCut <- cutree(clusters, 12)
split(names(clusterCut),clusterCut)
## $`1`
## [1] "antelope" "dalmatian" "persian+cat" "horse"
## [5] "german+shepherd" "siamese+cat" "mole" "tiger"
## [9] "hippopotamus" "leopard" "moose" "elephant"
## [13] "ox" "sheep" "hamster" "rhinoceros"
## [17] "rabbit" "wolf" "chihuahua" "rat"
## [21] "weasel" "buffalo" "deer" "bobcat"
## [25] "pig" "lion" "mouse" "collie"
## [29] "raccoon" "cow"
##
## $`2`
## [1] "grizzly+bear"
##
## $`3`
## [1] "killer+whale" "beaver" "seal" "otter" "walrus"
## [6] "dolphin"
##
## $`4`
## [1] "blue+whale" "humpback+whale"
##
## $`5`
## [1] "skunk"
##
## $`6`
## [1] "spider+monkey" "gorilla" "chimpanzee" "squirrel"
##
## $`7`
## [1] "fox"
##
## $`8`
## [1] "bat"
##
## $`9`
## [1] "giraffe"
##
## $`10`
## [1] "zebra"
##
## $`11`
## [1] "giant+panda"
##
## $`12`
## [1] "polar+bear"
Debido a que la medida de proximidad single linkage es más sensible al ruido intermedio y menos sensible a los outliers permite detectar que el murciélago es muy diferente a los otros animales, también permite distinguir a los animales marinos ya que son muy diferentes del resto. Sin embargo, debido al parecido entre los otros animales, las clasificaciones de éstos son más difusas y difíciles de notar al utilizar esta medida, pero sí es posible ver que se agrupan los primates, algunos felinos y animales domésticos.
Ahora realizamos el agrupamiento utilizando Complete linkage
clusters <- hclust(dist(scale(datos)), method = "complete")
plot(clusters, col = "blue")
Cortamos para formar 12 clústers
clusterCut <- cutree(clusters, 12)
split(names(clusterCut),clusterCut)
## $`1`
## [1] "antelope" "horse" "moose" "ox" "sheep" "buffalo"
## [7] "zebra" "deer" "pig" "cow"
##
## $`2`
## [1] "grizzly+bear" "polar+bear"
##
## $`3`
## [1] "killer+whale" "seal" "walrus" "dolphin"
##
## $`4`
## [1] "beaver" "dalmatian" "persian+cat" "german+shepherd"
## [5] "siamese+cat" "chihuahua" "weasel" "otter"
## [9] "collie"
##
## $`5`
## [1] "blue+whale" "humpback+whale"
##
## $`6`
## [1] "skunk" "mole" "hamster" "squirrel" "rabbit" "rat" "mouse"
## [8] "raccoon"
##
## $`7`
## [1] "tiger" "leopard" "fox" "wolf" "bobcat" "lion"
##
## $`8`
## [1] "hippopotamus" "elephant" "rhinoceros"
##
## $`9`
## [1] "spider+monkey" "gorilla" "chimpanzee"
##
## $`10`
## [1] "bat"
##
## $`11`
## [1] "giraffe"
##
## $`12`
## [1] "giant+panda"
Al utilizar la medida complete linkage, debido a que estamos utilizando el máximo entre grupos tenemos una sensibilidad mayor a los outilers por lo que estos permite distinguir entre animales que son parecidos pero no se encuentran necesariamente en la misma categoría, por ejemplo se revuelven los animales domésticos con los semiacuáticos. Pero los demás grupos sí se observan con un mejor sentido, ya que por ejemplo los 2 osos se encuentran en un grupo, los animales marinos en otro, también están separadas las ballenas más grandes, los felinos y caninos salvajes están agrupados, los primates y los roedores también.
Ahora realizamos el agrupamiento utilizando Ward linkage
clusters <- hclust(dist(scale(datos)), method = "ward.D")
plot(clusters, col = "blue")
Cortamos para formar 12 clústers
clusterCut <- cutree(clusters, 12)
split(names(clusterCut),clusterCut)
## $`1`
## [1] "antelope" "horse" "moose" "giraffe" "zebra" "deer"
##
## $`2`
## [1] "grizzly+bear" "giant+panda" "polar+bear"
##
## $`3`
## [1] "killer+whale" "beaver" "seal" "otter" "walrus"
## [6] "dolphin"
##
## $`4`
## [1] "dalmatian" "persian+cat" "german+shepherd" "siamese+cat"
## [5] "chihuahua" "collie"
##
## $`5`
## [1] "blue+whale" "humpback+whale"
##
## $`6`
## [1] "skunk" "mole" "hamster" "squirrel" "rabbit" "mouse"
##
## $`7`
## [1] "tiger" "leopard" "bobcat" "lion"
##
## $`8`
## [1] "hippopotamus" "elephant" "rhinoceros"
##
## $`9`
## [1] "spider+monkey" "gorilla" "chimpanzee"
##
## $`10`
## [1] "ox" "sheep" "buffalo" "pig" "cow"
##
## $`11`
## [1] "fox" "wolf" "rat" "weasel" "raccoon"
##
## $`12`
## [1] "bat"
El agrupamiento realizado al utilizar el método de mínima varianza de Ward parece ser bastante adecuado, ahora detallamos los 12 clúster obtenidos aquí:
Ahora respondemos las siguientes preguntas de manera precisa:
La medida de proximidad single permite detectar animales con características muy distinas como es el murciélago y permite separar muy bien entre animales marinos y terrestres. Sin embargo, tiene algunas confusiones entre animales terrestres similares pero que naturalmente no clasificaríamos en el mismo grupo (por ejemplo, la ardilla con los primates o los caninos salvajes con los domésticos). La medida complete confunde a los animales domésticos con los semiacuáticos, pero en general tiene un buen desempeño. La medida de Ward parece muy adecuada para clasificar e incluso distingue muy bien entre felinos y caninos que tienen diferencias no tan evidentes.
Los grupos sí son razonables salvo los detalles que ya se han comentado antes para las medidas single y complete.
Si deseamos tener una propuesta de clasificación estableciendo semejanzas entre animales a grandes razgos definitivamente podríamos utilizar alguno de los algoritmos de clustering propuestos, pero esto dependerá de las características que se hayan medido, en este ejemplo tenemos más información (85 columnas) que observaciones (50), por lo que si queremos alguna forma específica de clasificar (como colores) y éstas medidas no se encuentran determinadas de alguna manera no podría cumplir este objetivo. Además, este tipo de métodos están diseñados para agrupar y no para el objetivo de clasificación.
En este caso la función linkage que realizó una clasificación más sensata fue la de ward como ya se comentó antes.